/*
 * Copyright (C) 2010 M. Hautle.
 * 
 * This file is part of SimpleEL.
 * 
 * SimpleEL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * SimpleEL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with SimpleEL. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.simpleel.util;

import ch.simpleel.internal.*;

/**
 * Helper evaluating simple EL expressions on a beans.<br>
 * Currently the following features were supported (also in combination):<br>
 * - Nested properties (<code>address.city.code</code>)<br>
 * - Array/listelements (<code>address[2]</code>)<br>
 * - Mapelements identified by their key (<code>members['john']</code>)<br>
 * 
 * @author M. Hautle
 */
public class ELHelper {
    /**
     * Hidden constructor.
     */
    private ELHelper() {
    }

    /**
     * Returns the name of the last property in the given expression.
     * 
     * @param el The expression
     * @return The last part of the expression
     * @throws IllegalArgumentException If the expression does not end with a property
     */
    public static String getLastProperty(String el) {
        final int index = el.lastIndexOf('.');
        final int indexed = el.lastIndexOf(']');
        if (indexed > index)
            throw new IllegalArgumentException(el + " does not end with a property!");
        if (index > 0)
            return el.substring(index + 1);
        return el;
    }

    /**
     * Returns the part of the expression before it's last segment.<br>
     * Here some examples:<br>
     * <code>foo.bar</code> will return <code>foo</code><br>
     * <code>foo.bar[1]</code> will return <code>foo.bar</code><br>
     * 
     * @param el The expression
     * @return The parent path, so the part before the last segment
     * @throws IllegalArgumentException If the expression has no parent path, if your not sure if there is a parent then call first
     *             {@link #isSimpleProperty(String)} to check
     */
    public static String getParentPath(String el) {
        final int index = el.lastIndexOf('.');
        final int indexed = el.lastIndexOf('[');
        // nested property?
        if (index > indexed)
            return el.substring(0, index);
        // indexed property?
        if (indexed > 0)
            return el.substring(0, indexed);
        // no parent
        throw new IllegalArgumentException(el + " has no parent path!");
    }

    /**
     * Returns the last segment of the given expression.<br>
     * Here some examples:<br>
     * <code>foo</code> will return <code>foo</code><br>
     * <code>foo.bar</code> will return <code>bar</code><br>
     * <code>foo.bar[1]</code> will return <code>[1]</code><br>
     * 
     * @param el The expression
     * @return The last segment of the expression
     */
    public static String getLastSegment(String el) {
        final int index = el.lastIndexOf('.');
        final int indexed = el.lastIndexOf('[');
        // nested property?
        if (index > indexed)
            return el.substring(index + 1);
        // indexed property?
        if (indexed > 0)
            return el.substring(indexed);
        // simple property
        return el;
    }

    /**
     * Checks wherever the given expression is just an property access (so that it calls only a getter/setter).
     * 
     * @param el The expression
     * @return True if it's just a flat property access
     */
    public static boolean isSimpleProperty(String el) {
        return ELUtils.isSimpleProperty(el);
    }

    /**
     * Ensures that the given expression is valid, if not a {@link IllegalArgumentException} will be thrown.
     * 
     * @param el The expression to check
     * @throws IllegalArgumentException If the EL expression is not valid.
     */
    public static void checkEL(String el) throws IllegalArgumentException {
        ELUtils.checkEL(el);
    }

    /**
     * Checks the given expression on syntactical correctness.
     * 
     * @param el The expression to check
     * @return True if the expression is valid
     */
    public static boolean isValid(String el) {
        return ELUtils.isValid(el);
    }
}
